<?php

/**
 * Maikuro Framework
 *
 * LICENSE:
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * The license is bundled with this package in the file LICENSE.txt.
 * You may also obtain a copy of the License at this URL:
 * http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 *
 * See the License for the specific language governing permissions and
 * limitations under the License.
 *
 * @copyright  Copyright (c) 2010, Jonathan Hedrén
 * @author     Jonathan Hedrén <jonathan.hedren@gmail.com>
 * @license    http://www.apache.org/licenses/LICENSE-2.0 Apache License, Version 2.0
 */

/**
 * The Mail class represents an email.
 */
class Mail
{
    const TO = 'To';
    const FROM = 'From';
    const BCC = 'Bcc';
    const CC = 'Cc';
    const REPLY_TO = 'Reply-To';
    const SENDER = 'Sender';
    const SUBJECT = 'Subject';
    const RETURN_PATH = 'Return-Path';

    /**
     * The mail body.
     *
     * @var string
     */
    protected $body;
    
    /**
     * Mail headers.
     *
     * @var array
     */
    protected $headers = array();

    /**
     * Adds a BCC to the mail.
     *
     * @param string $bcc
     * @param string $bccName
     * @return Mail
     */
    public function addBcc($bcc, $bccName = null)
    {
        if (!is_array($bcc)) {
            $bcc = array($bcc => $bccName);
        }
        $current = $this->getHeader(self::BCC);
        $this->setHeader(self::BCC, array_merge((array) $current, $bcc));
        return $this;
    }

    /**
     * Adds a CC to the mail.
     *
     * @param string $cc
     * @param string $ccName
     * @return Mail
     */
    public function addCc($cc, $ccName = null)
    {
        if (!is_array($cc)) {
            $cc = array($cc => $ccName);
        }
        $current = $this->getHeader(self::CC);
        $this->setHeader(self::CC, array_merge((array) $current, $cc));
        return $this;
    }

    /**
     * Adds a mail recipient.
     *
     * @param string $to
     * @param string $toName
     * @return Mail
     */
    public function addTo($to, $toName = null)
    {
        if (!is_array($to)) {
            $to = array($to => $toName);
        }
        $current = $this->getHeader(self::TO);
        $this->setHeader(self::TO, array_merge((array) $current, $to));
        return $this;
    }

    /**
     * Returns the mail body.
     *
     * @return string
     */
    public function getBody()
    {
        return $this->body;
    }

    /**
     * Returns the From header.
     *
     * @return string
     */
    public function getFrom()
    {
        return $this->getHeader(self::FROM);
    }

    /**
     * Returns the specified header.
     *
     * @param string $header
     * @return string
     */
    public function getHeader($header)
    {
        return isset($this->headers[$header]) ? $this->headers[$header] : null;
    }

    /**
     * Returns all headers.
     *
     * @return array
     */
    public function getHeaders($formatted = true, array $omitted = null)
    {
        $headers = $this->headers;
        if ($omitted !== null) {
            foreach ($omitted as $omittedHeader) {
                unset($headers[$omittedHeader]);
            }
        }

        if ($formatted) {
            $rfc2822 = '';
            foreach ($headers as $header => $value) {
                if (is_array($value)) {
                    $addresses = $value;
                    $value = '';
                    foreach ($addresses as $email => $name) {
                        $value .= $name . ' <' . $email . '>, ';
                    }
                    $value = rtrim($value, ', ');
                }
                $rfc2822 .= $header . ': ' . $value . "\r\n";
            }
            return $rfc2822;
        }
        return $headers;
    }

    /**
     * Returns the Sender header.
     *
     * @return string
     */
    public function getSender($formatted = true)
    {
        if ($formatted) {
            // TODO: if is_array
            return self::SENDER . ': ' . $this->getHeader(self::SENDER);
        }
        return $this->getHeader(self::SENDER);
    }
    
    /**
     * Returns the subject.
     *
     * @return string
     */
    public function getSubject($formatted = true)
    {
        if ($formatted) {
            return self::SUBJECT . ': ' . $this->getHeader(self::SUBJECT);
        }
        return $this->getHeader(self::SUBJECT);
    }

    /**
     * Returns the To header.
     *
     * @return string
     */
    public function getTo($formatted = true)
    {
        if ($formatted) {
            $rfc2822 = '';
            foreach ($this->getHeader(self::TO) as $to => $toName) {
                $rfc2822 .= $toName . ' <' . $to . '>, ';
            }
            return rtrim($rfc2822, ', ');
        }
        return $this->getHeader(self::TO);
    }

    /**
     * Sets BCC('s).
     *
     * @param string|array $bcc
     * @return Mail
     */
    public function setBcc($bcc, $bccName = null)
    {
        //Filter::email($from);
        if (!is_array($bcc)) {
            $bcc = array($bcc => $bccName);
        }
        return $this->setHeader(self::BCC, $bcc);
    }

    /**
     * Sets the mail body.
     *
     * @param string $body
     * @return Mail
     */
    public function setBody($body)
    {
        $this->body = wordwrap($body, 70);
        return $this;
    }

    /**
     * Sets CC('s).
     *
     * @param string|array $cc
     * @return Mail
     */
    public function setCc($cc, $ccName = null)
    {
        if (!is_array($cc)) {
            $cc = array($cc => $ccName);
        }
        return $this->setHeader(self::CC, $cc);
    }

    /**
     * Sets the From header.
     *
     * @param string $from
     * @return Mail
     */
    public function setFrom($from)
    {
        //Filter::email($from);
        return $this->setHeader(self::FROM, $from);
    }

    /**
     * Sets a header.
     *
     * @param string $header
     * @param string $value
     * @return Mail
     */
    public function setHeader($header, $value)
    {
        $this->headers[$header] = $value;
        return $this;
    }

    /**
     * Sets the Reply-To header.
     *
     * @param string $replyTo
     * @return Mail
     */
    public function setReplyTo($replyTo)
    {
        return $this->setHeader(self::REPLY_TO, $replyTo);
    }

    /**
     * Sets the Return-Path header.
     *
     * @param string $returnPath
     * @return Mail
     */
    public function setReturnPath($returnPath)
    {
        return $this->setHeader(self::RETURN_PATH, $returnPath);
    }

    /**
     * Sets the Sender header.
     *
     * @param string $sender
     * @return Mail
     */
    public function setSender($sender)
    {
        return $this->setHeader(self::SENDER, $sender);
    }

    /**
     * Sets the Subject header.
     *
     * @param string $subject
     * @return Mail
     */
    public function setSubject($subject)
    {
        return $this->setHeader(self::SUBJECT, $subject);
    }

    /**
     * Sets the To header.
     *
     * @param string|array $to
     * @return Mail
     */
    public function setTo($to, $toName = null) {
        //Filter::email($to);
        if (!is_array($to)) {
            $to = array($to => $toName);
        }
        $this->setHeader(self::TO, $to);
        return $this;
    }

}